package org.qpcr.community.project.service;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.fasterxml.jackson.core.type.TypeReference;
import com.fasterxml.jackson.databind.ObjectMapper;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.apache.poi.ss.usermodel.Cell;
import org.apache.poi.ss.usermodel.Row;
import org.apache.poi.ss.usermodel.Sheet;
import org.apache.poi.ss.usermodel.Workbook;
import org.apache.poi.ss.util.CellRangeAddress;
import org.apache.poi.xssf.usermodel.XSSFWorkbook;
import org.hswebframework.reactor.excel.CellDataType;
import org.hswebframework.reactor.excel.ExcelHeader;
import org.hswebframework.reactor.excel.ReactorExcel;
import org.hswebframework.reactor.excel.spec.SheetSpec;
import org.hswebframework.web.crud.service.GenericReactiveCrudService;
import org.qpcr.community.device.entity.DeviceProperty;
import org.qpcr.community.io.file.FileManager;
import org.qpcr.community.io.file.FileOption;
import org.qpcr.community.project.enums.ExportType;
import org.qpcr.community.project.model.entity.DataAnalysisExportAmplificationParam;
import org.qpcr.community.project.model.entity.DataAnalysisExperimentalRecordsEntity;
import org.qpcr.community.project.model.entity.ExperimentalRecordsInstanceEntity;
import org.qpcr.community.project.model.entity.ExportAmplificationParam;
import org.qpcr.community.project.model.entity.FileCenterInstanceEntity;
import org.qpcr.community.project.model.entity.excel.*;
import org.qpcr.community.project.web.excel.sequence.Group;
import org.qpcr.community.project.web.excel.sequence.Panel;
import org.qpcr.community.project.web.excel.sequence.SequenceStep;
import org.springframework.core.io.buffer.DataBufferFactory;
import org.springframework.core.io.buffer.DataBufferUtils;
import org.springframework.core.io.buffer.DefaultDataBufferFactory;
import org.springframework.http.HttpHeaders;
import org.springframework.http.codec.multipart.FilePart;
import org.springframework.http.server.reactive.ServerHttpResponse;
import org.springframework.stereotype.Service;
import org.springframework.web.bind.annotation.RequestBody;
import reactor.core.publisher.Flux;
import reactor.core.publisher.Mono;

import java.io.ByteArrayInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.util.*;
import java.util.function.Consumer;

@Service
@Slf4j
@RequiredArgsConstructor
public class DataAnalysisService extends GenericReactiveCrudService<ExperimentalRecordsInstanceEntity, String> {
    private final FileManager fileManager;
    private final LocalFileCenterInstanceService fileCenterInstanceService;

    DataBufferFactory bufferFactory = new DefaultDataBufferFactory();

    public Mono<ExcelDataResponse> uploadExcel(FilePart filePart,String dataId){
        return filePart.content()
                       .collectList()
                       .flatMap(dataBuffers -> {
                           if (dataBuffers.isEmpty()) {
                               return Mono.error(new IllegalArgumentException("上传的文件为空"));
                           }

                           byte[] bytes = dataBuffers.stream()
                                                     .map(dataBuffer -> {
                                                         byte[] array = new byte[dataBuffer.readableByteCount()];
                                                         dataBuffer.read(array);
                                                         DataBufferUtils.release(dataBuffer);
                                                         return array;
                                                     })
                                                     .reduce(new byte[0], (a, b) -> {
                                                         byte[] result = new byte[a.length + b.length];
                                                         System.arraycopy(a, 0, result, 0, a.length);
                                                         System.arraycopy(b, 0, result, a.length, b.length);
                                                         return result;
                                                     });

                           if (bytes.length == 0) {
                               return Mono.error(new IllegalArgumentException("上传的文件大小为0"));
                           }

                           ExcelDataResponse response = new ExcelDataResponse();
                           ChartResult chartResult = new ChartResult();
                           response.setFileName(filePart.filename());
                           response.setDataId(dataId);
                           response.setStatus("解析成功");
                           try (InputStream is = new ByteArrayInputStream(bytes);
                                Workbook workbook = new XSSFWorkbook(is)) {

                               // Parse Temperature Data
                               Sheet tempSheet = workbook.getSheet("温度");
                               if (tempSheet != null) {
                                   response.setTemperatureData(parseTemperatureData(tempSheet));
                               }

                               // Parse Voltage Current Data
                               Sheet voltageSheet = workbook.getSheet("电压电流");
                               if (voltageSheet != null) {
                                   response.setVoltageCurrentData(parseVoltageCurrentData(voltageSheet));
                               }

                               // Parse Amplification Data
                               Sheet ampSheet = workbook.getSheet("扩增");
                               if (ampSheet != null) {
                                   response.setAmplificationData(parseAmplificationData(ampSheet,chartResult));
                               }

                               // Parse Fluorescence Voltage Data
                               Sheet fluoVoltSheet = workbook.getSheet("荧光（电压）");
                               if (fluoVoltSheet != null) {
                                   response.setFluorescenceVoltageData(parseFluorescenceVoltageData(fluoVoltSheet,chartResult));
                               }

                               // Parse Fluorescence Source Data
                               Sheet fluoSourceSheet = null == workbook.getSheet("荧光(源数据)") ? workbook.getSheet("荧光(原数据)") : workbook.getSheet("荧光(源数据)");

                               if (fluoSourceSheet != null) {
                                   response.setFluorescenceSourceData(parseFluorescenceSourceData(fluoSourceSheet,chartResult));
                               }

                               // Parse CT Data
                               Sheet ctSheet = workbook.getSheet("CT");
                               if (ctSheet != null) {
                                   response.setCtData(parseCTData(ctSheet));
                               }

                               // Parse Melt Curve Raw Data
                               Sheet meltRawSheet = workbook.getSheet("熔解（原数据）");
                               if (meltRawSheet != null) {
                                   response.setMeltCurveRawData(parseMeltCurveRawData(meltRawSheet,chartResult));
                               }

                               // Parse Melt Curve Processed Data
                               Sheet meltProcessedSheet = workbook.getSheet("熔解（后处理）");
                               if (meltProcessedSheet != null) {
                                   response.setMeltCurveProcessedData(parseMeltCurveProcessedData(meltProcessedSheet));
                               }

                               // Parse Melt Curve Result Data
                               Sheet meltResultSheet = workbook.getSheet("熔解结果");
                               if (meltResultSheet != null) {
                                   response.setMeltCurveResultData(parseMeltCurveResultData(meltResultSheet));
                               }
                               response.setChartResult(chartResult);
                           } catch (IOException e) {
                               throw new RuntimeException("Error processing Excel file", e);
                           }
                           return Mono.just(response);

                       });
    }




    public Mono<Void> exportAmplification(ServerHttpResponse response, DataAnalysisExportAmplificationParam exportParam){
        String type="zh";


        return ReactorExcel
            .xlsxWriter()
            .multiSheet()
            .sheet(this.getRecordSheet(exportParam))
            .sheet(this.getDeviceStateData(exportParam))
            .sheet(this.getTemperatureReportData(exportParam))
             .sheet(this.getVolAndCurrent(exportParam))
             .sheet(this.getAmplificationData(exportParam))//扩增替换
             .sheet(this.getMeteringDataReport(exportParam))
             .sheet(this.getMeteringSaveDataReport(exportParam))
             .sheet(this.getCT(exportParam)) //CT替换
             .sheet(this.getMeltCurveData(exportParam))
             .sheet(this.getMeltCurveCuleData(exportParam))//熔解计算后替换
             .sheet(this.getTrim(exportParam)) //trim替换
            .writeBytes(1024 * 1024)
//             .doOnNext(bytes -> System.out.println("数据流 next 了，字节数：" + bytes.length)) // 加日志
//            .doOnComplete(() -> System.out.println("数据流 complete 了")) // 加日志
            .map(bufferFactory::wrap)
            .as(response::writeWith)
            .doOnError(err -> log.error(err.getMessage(), err));
//            .as(dataBuffer -> {
//                String fileName = exportParam.getFileName() + ".xlsx";
//                // 保存附件
//                String finalFileName = fileName;
//                try {
//                    response.getHeaders().set(HttpHeaders.CONTENT_DISPOSITION,
//                                              "attachment; filename=".concat(URLEncoder.encode(fileName, StandardCharsets.UTF_8
//                                                  .displayName())));
//                } catch (UnsupportedEncodingException e) {
//                    throw new RuntimeException(e);
//                }
//                return fileManager
//                    .saveFile(fileName, dataBuffer, FileOption.publicAccess)
//                    .flatMap(fileInfo -> {
//                        FileCenterInstanceEntity fileCenterInstanceEntity = new FileCenterInstanceEntity();
//                        fileCenterInstanceEntity.setName(finalFileName);
//                        fileCenterInstanceEntity.setType(ExportType.experimentalRecord.getValue());
//                        fileCenterInstanceEntity.setFileId(fileInfo.getId());
//                        fileCenterInstanceEntity.setConfiguration(fileInfo.getOthers());
//                        return fileCenterInstanceService.save(fileCenterInstanceEntity)
//                                                        .then(response.writeWith(dataBuffer));
//                    });
//            }).doOnError(err -> log.error(err.getMessage(), err));
    }


    /*******************************************************************************************************************/
    /*******************************************************Private方法**************************************************/
    /*******************************************************************************************************************/

    private List<TemperatureData> parseTemperatureData(Sheet sheet) {
        List<TemperatureData> dataList = new ArrayList<>();
        for (int i = 1; i <= sheet.getLastRowNum(); i++) {
            Row row = sheet.getRow(i);
            if (row != null) {
                TemperatureData data = new TemperatureData();
                data.setTime(getDoubleValue(row.getCell(0)));
                data.setRtdDes(getDoubleValue(row.getCell(1)));
                data.setReagentTar(getDoubleValue(row.getCell(2)));
                data.setSet(getDoubleValue(row.getCell(3)));
                data.setReagent(getDoubleValue(row.getCell(4)));
                data.setRtdReal(getDoubleValue(row.getCell(5)));
                data.setCooler(getDoubleValue(row.getCell(6)));
                data.setAssistedRtdA(getDoubleValue(row.getCell(7)));
                data.setAssistedRtdB(getDoubleValue(row.getCell(8)));
                data.setAssistedRtdC(getDoubleValue(row.getCell(9)));
                dataList.add(data);
            }
        }
        return dataList;
    }

    private List<VoltageCurrentData> parseVoltageCurrentData(Sheet sheet) {
        List<VoltageCurrentData> dataList = new ArrayList<>();
        for (int i = 1; i <= sheet.getLastRowNum(); i++) {
            Row row = sheet.getRow(i);
            if (row != null) {
                VoltageCurrentData data = new VoltageCurrentData();
                data.setTime(getDoubleValue(row.getCell(0)));
                data.setMainVoltage(getDoubleValue(row.getCell(1)));
                data.setMainCurrent(getDoubleValue(row.getCell(2)));
                data.setAVoltage(getDoubleValue(row.getCell(3)));
                data.setACurrent(getDoubleValue(row.getCell(4)));
                data.setBVoltage(getDoubleValue(row.getCell(5)));
                data.setBCurrent(getDoubleValue(row.getCell(6)));
                data.setCVoltage(getDoubleValue(row.getCell(7)));
                data.setCCurrent(getDoubleValue(row.getCell(8)));
                dataList.add(data);
            }
        }
        return dataList;
    }

    private List<AmplificationData> parseAmplificationData(Sheet sheet, ChartResult chartResult) {
        List<AmplificationData> dataList = new ArrayList<>();
        List<ChartData> chartDataList = new ArrayList<>();
        for (int i = 1; i <= sheet.getLastRowNum(); i++) {
            Row row = sheet.getRow(i);
            if (row != null) {
                AmplificationData data = new AmplificationData();
                data.setCycle(getIntValue(row.getCell(0)));
                data.setFluoreVic(getDoubleValue(row.getCell(1)));
                data.setFluoreCy5(getDoubleValue(row.getCell(2)));
                data.setFluoreFam(getDoubleValue(row.getCell(3)));
                data.setFluoreRox(getDoubleValue(row.getCell(4)));
                dataList.add(data);

//                {"ch4_light":0,"ch3_light":0,"ch2_light":0,"cycle":1}

                JSONObject jsonObject = new JSONObject();
                jsonObject.put("ch4_light",data.getFluoreVic());
                jsonObject.put("ch3_light",data.getFluoreCy5());
                jsonObject.put("ch2_light",data.getFluoreFam());
                jsonObject.put("cycle",data.getCycle());


                ChartData chartData = new ChartData();
                chartData.setProperty("AmplificationData");
                chartData.setPropertyName("扩增");
                chartData.setValue(jsonObject.toString());
                chartData.setFormatValue(jsonObject.toString());
                chartDataList.add(chartData);
            }
        }
        chartResult.setTotal(dataList.size());
        chartResult.setPageSize(dataList.size());
        chartResult.setPageIndex(1);
        chartResult.setAmplificationDataReport(chartDataList);
        return dataList;
    }

    private List<FluorescenceVoltageData> parseFluorescenceVoltageData(Sheet sheet,ChartResult chartResult) {
        List<FluorescenceVoltageData> dataList = new ArrayList<>();
        List<ChartData> chartDataList = new ArrayList<>();
        for (int i = 1; i <= sheet.getLastRowNum(); i++) {
            Row row = sheet.getRow(i);
            if (row != null) {
                FluorescenceVoltageData data = new FluorescenceVoltageData();
                data.setCycle(getIntValue(row.getCell(0)));
                data.setFluoreVic(getDoubleValue(row.getCell(1)));
                data.setFluoreCy5(getDoubleValue(row.getCell(2)));
                data.setFluoreFam(getDoubleValue(row.getCell(3)));
                data.setFluoreRox(getDoubleValue(row.getCell(4)));
                data.setFluoreVicOriginal(getDoubleValue(row.getCell(5)));
                data.setFluoreCy5Original(getDoubleValue(row.getCell(6)));
                data.setFluoreFamOriginal(getDoubleValue(row.getCell(7)));
                data.setFluoreRoxOriginal(getDoubleValue(row.getCell(8)));
                dataList.add(data);


//                {"ch1_original":0.1534000039100647,"ch1_value":1534,"ch3_original":0.382999986410141,"ch3_value":3830,"ch2_original":0.07259999960660934,"count":1,"calc":true,"ch2_value":726,"ch4_original":0.11569999903440475,"ch4_value":1157}

                JSONObject jsonObject = new JSONObject();

                jsonObject.put("ch1_original",data.getFluoreVicOriginal());
                jsonObject.put("ch1_value",data.getFluoreVic());
                jsonObject.put("ch3_original",data.getFluoreFamOriginal());
                jsonObject.put("ch3_value",data.getFluoreFam());
                jsonObject.put("ch2_original",data.getFluoreCy5Original());
                jsonObject.put("count",data.getCycle());
                jsonObject.put("calc",true);
                jsonObject.put("ch2_value",data.getFluoreCy5());
                jsonObject.put("ch4_original",data.getFluoreRoxOriginal());
                jsonObject.put("ch4_value",data.getFluoreRox());


                ChartData chartData = new ChartData();
                chartData.setProperty("MeteringDataReport");
                chartData.setPropertyName("测光曲线");
                chartData.setValue(jsonObject.toString());
                chartData.setFormatValue(jsonObject.toString());
                chartDataList.add(chartData);
            }
        }
        chartResult.setTotal(dataList.size());
        chartResult.setPageSize(dataList.size());
        chartResult.setPageIndex(1);
        chartResult.setMeteringDataReport(chartDataList);
        return dataList;
    }

    private List<FluorescenceSourceData> parseFluorescenceSourceData(Sheet sheet,ChartResult chartResult) {
        List<FluorescenceSourceData> dataList = new ArrayList<>();
        List<ChartData> chartDataList = new ArrayList<>();
        for (int i = 1; i <= sheet.getLastRowNum(); i++) {
            Row row = sheet.getRow(i);
            if (row != null) {
                FluorescenceSourceData data = new FluorescenceSourceData();
                data.setCycle(getIntValue(row.getCell(0)));
                data.setFluoreVic(getDoubleValue(row.getCell(1)));
                data.setFluoreCy5(getDoubleValue(row.getCell(2)));
                data.setFluoreFam(getDoubleValue(row.getCell(3)));
                data.setFluoreRox(getDoubleValue(row.getCell(4)));
                data.setFluoreVicOriginal(getDoubleValue(row.getCell(5)));
                data.setFluoreCy5Original(getDoubleValue(row.getCell(6)));
                data.setFluoreFamOriginal(getDoubleValue(row.getCell(7)));
                data.setFluoreRoxOriginal(getDoubleValue(row.getCell(8)));
                dataList.add(data);

//                {"ch_vic":472,"vic":472,"ch_cy5":-1526,"fam":-6,"ch_rox":705,"count":1,"rox":705,"ch_fam":-6,"cy5":-1526}
                JSONObject jsonObject = new JSONObject();
                jsonObject.put("ch_vic", data.getFluoreVicOriginal());
                jsonObject.put("vic", data.getFluoreVic());
                jsonObject.put("ch_cy5", data.getFluoreCy5Original());
                jsonObject.put("fam", data.getFluoreFam());
                jsonObject.put("ch_rox", data.getFluoreRoxOriginal());
                jsonObject.put("count", data.getCycle());
                jsonObject.put("rox", data.getFluoreRox());
                jsonObject.put("ch_fam", data.getFluoreFamOriginal());
                jsonObject.put("cy5", data.getFluoreCy5());

                ChartData chartData = new ChartData();
                chartData.setProperty("MeteringSaveData");
                chartData.setPropertyName("荧光去串后（计算后）");
                chartData.setValue(jsonObject.toString());
                chartData.setFormatValue(jsonObject.toString());
                chartDataList.add(chartData);
            }
        }
        chartResult.setTotal(dataList.size());
        chartResult.setPageSize(dataList.size());
        chartResult.setPageIndex(1);
        chartResult.setChartData(chartDataList);
        return dataList;
    }

    private List<CTData> parseCTData(Sheet sheet) {
        List<CTData> dataList = new ArrayList<>();
        for (int i = 1; i <= sheet.getLastRowNum(); i++) {
            Row row = sheet.getRow(i);
            if (row != null) {
                CTData data = new CTData();
                data.setFluoreVic(getDoubleValue(row.getCell(0)));
                data.setFluoreCy5(getDoubleValue(row.getCell(1)));
                data.setFluoreFam(getDoubleValue(row.getCell(2)));
                data.setFluoreRox(getDoubleValue(row.getCell(3)));
                dataList.add(data);
            }
        }
        return dataList;
    }

    private List<MeltCurveRawData> parseMeltCurveRawData(Sheet sheet,ChartResult chartResult) {
        List<MeltCurveRawData> dataList = new ArrayList<>();
        List<ChartData> chartDataList = new ArrayList<>();
        for (int i = 1; i <= sheet.getLastRowNum(); i++) {
            Row row = sheet.getRow(i);
            if (row != null) {
                MeltCurveRawData data = new MeltCurveRawData();
                data.setVicTemperature(getDoubleValue(row.getCell(0)));
                data.setFluoreVic(getDoubleValue(row.getCell(1)));
                data.setCy5Temperature(getDoubleValue(row.getCell(2)));
                data.setFluoreCy5(getDoubleValue(row.getCell(3)));
                data.setFamTemperature(getDoubleValue(row.getCell(4)));
                data.setFluoreFam(getDoubleValue(row.getCell(5)));
                data.setRoxTemperature(getDoubleValue(row.getCell(6)));
                data.setFluoreRox(getDoubleValue(row.getCell(7)));
                dataList.add(data);


//                {"ch1_light":"130","ch4_light":"666","ch3_light":"-261","ch2_light":"70","temperatur1":49.02000045776367,"temperatur2":49.02000045776367,"temperatur3":49.02000045776367,"temperatur4":49.02000045776367}
                JSONObject jsonObject = new JSONObject();
                jsonObject.put("ch1_light", data.getFluoreVic());
                jsonObject.put("ch4_light", data.getFluoreRox());
                jsonObject.put("ch3_light", data.getFluoreFam());
                jsonObject.put("ch2_light", data.getFluoreCy5());
                jsonObject.put("temperatur1", data.getVicTemperature());
                jsonObject.put("temperatur2", data.getCy5Temperature());
                jsonObject.put("temperatur3", data.getFamTemperature());
                jsonObject.put("temperatur4", data.getRoxTemperature());


                ChartData chartData = new ChartData();
                chartData.setProperty("MeltCurveData");
                chartData.setPropertyName("熔解曲线");
                chartData.setValue(jsonObject.toString());
                chartData.setFormatValue(jsonObject.toString());
                chartDataList.add(chartData);
            }
        }
        chartResult.setTotal(dataList.size());
        chartResult.setPageSize(dataList.size());
        chartResult.setPageIndex(1);
        chartResult.setChartDataMeltCurve(chartDataList);
        return dataList;
    }

    private List<MeltCurveProcessedData> parseMeltCurveProcessedData(Sheet sheet) {
        List<MeltCurveProcessedData> dataList = new ArrayList<>();
        for (int i = 1; i <= sheet.getLastRowNum(); i++) {
            Row row = sheet.getRow(i);
            if (row != null) {
                MeltCurveProcessedData data = new MeltCurveProcessedData();
                data.setTVic(getDoubleValue(row.getCell(0)));
                data.setDiffVic(getDoubleValue(row.getCell(1)));
                data.setTCy5(getDoubleValue(row.getCell(2)));
                data.setDiffCy5(getDoubleValue(row.getCell(3)));
                data.setTFam(getDoubleValue(row.getCell(4)));
                data.setDiffFam(getDoubleValue(row.getCell(5)));
                data.setTRox(getDoubleValue(row.getCell(6)));
                data.setDiffRox(getDoubleValue(row.getCell(7)));
                dataList.add(data);
            }
        }
        return dataList;
    }

    private List<MeltCurveResultData> parseMeltCurveResultData(Sheet sheet) {
        List<MeltCurveResultData> dataList = new ArrayList<>();
        for (int i = 1; i <= sheet.getLastRowNum(); i++) {
            Row row = sheet.getRow(i);
            if (row != null) {
                MeltCurveResultData data = new MeltCurveResultData();
                data.setTmVic(getDoubleValue(row.getCell(0)));
                data.setRmVic(getDoubleValue(row.getCell(1)));
                data.setTmCy5(getDoubleValue(row.getCell(2)));
                data.setRmCy5(getDoubleValue(row.getCell(3)));
                data.setTmFam(getDoubleValue(row.getCell(4)));
                data.setRmFam(getDoubleValue(row.getCell(5)));
                data.setTmRox(getDoubleValue(row.getCell(6)));
                data.setRmRox(getDoubleValue(row.getCell(7)));
                dataList.add(data);
            }
        }
        return dataList;
    }

    private Double getDoubleValue(Cell cell) {
        if (cell == null) {
            return null;
        }
        switch (cell.getCellType()) {
            case NUMERIC:
                return cell.getNumericCellValue();
            case STRING:
                try {
                    return Double.parseDouble(cell.getStringCellValue());
                } catch (NumberFormatException e) {
                    return null;
                }
            default:
                return null;
        }
    }

    private Integer getIntValue(Cell cell) {
        if (cell == null) {
            return null;
        }
        switch (cell.getCellType()) {
            case NUMERIC:
                return (int) cell.getNumericCellValue();
            case STRING:
                try {
                    return Integer.parseInt(cell.getStringCellValue());
                } catch (NumberFormatException e) {
                    return null;
                }
            default:
                return null;
        }
    }



    private Consumer<SheetSpec.HeaderSheetSpec> getTemperatureReportData(DataAnalysisExportAmplificationParam exportParam) {
        Flux<Map<String, Object>> dataStream = Flux.create(fluxSink -> {
            List<TemperatureData> temperatureData = exportParam.getTemperatureData();
            Map<String, Object> map = new HashMap<>();
            for (TemperatureData temperatureDatum : temperatureData) {
                map.put("sample_time", temperatureDatum.getTime());
                map.put("temp_rtd_expect", temperatureDatum.getRtdDes());
                map.put("reserved_power", temperatureDatum.getReagentTar());
                map.put("temp_goal", temperatureDatum.getSet());
                map.put("temp_forecast", temperatureDatum.getReagent());
                map.put("temp_rtd_actual", temperatureDatum.getRtdReal());
                map.put("temp_cold_head", temperatureDatum.getCooler());
                map.put("Assisted_RTD_A", temperatureDatum.getAssistedRtdA());
                map.put("Assisted_RTD_B", temperatureDatum.getAssistedRtdB());
                map.put("Assisted_RTD_C", temperatureDatum.getAssistedRtdC());
                fluxSink.next(map);
            }
            fluxSink.complete();
        });

        return sheet -> sheet.name("温度")
                             .header(new ExcelHeader("sample_time", "Time (s)", CellDataType.NUMBER))
                             .header(new ExcelHeader("temp_rtd_expect", "RTD_Des (Celsius Degree)", CellDataType.NUMBER))
                             .header(new ExcelHeader("reserved_power", "Reagent_Tar(Celsius Degree)", CellDataType.NUMBER))//Reserve_Power (Celsius Degree)
                             .header(new ExcelHeader("temp_goal", "Set (Celsius Degree)", CellDataType.NUMBER))
                             .header(new ExcelHeader("temp_forecast", "Reagent (Celsius Degree)", CellDataType.NUMBER))
                             .header(new ExcelHeader("temp_rtd_actual", "RTD_Real (Celsius Degree)", CellDataType.NUMBER)) //RTD_Real (Celsius Degree)
                             .header(new ExcelHeader("temp_cold_head", "Cooler (Celsius Degree)", CellDataType.NUMBER))
                             .header(new ExcelHeader("Assisted_RTD_A", "Assisted_RTD_A(Celsius Degree)", CellDataType.NUMBER))
                             .header(new ExcelHeader("Assisted_RTD_B", "Assisted_RTD_B(Celsius Degree)", CellDataType.NUMBER))
                             .header(new ExcelHeader("Assisted_RTD_C", "Assisted_RTD_C(Celsius Degree)", CellDataType.NUMBER))
                             .rows(dataStream);

    }

    private Consumer<SheetSpec.HeaderSheetSpec> getVolAndCurrent(DataAnalysisExportAmplificationParam exportParam) {

        Flux<Map<String, Object>> dataStream = Flux.create(fluxSink -> {
            List<VoltageCurrentData> voltageCurrentDatas = exportParam.getVoltageCurrentData();
            Map<String, Object> map = new HashMap<>();
            for (VoltageCurrentData voltageCurrentData : voltageCurrentDatas) {
                map.put("sample_time", voltageCurrentData.getTime());
                map.put("rtd_vol", voltageCurrentData.getMainVoltage());
                map.put("rtd_cur", voltageCurrentData.getMainCurrent());
                map.put("AVoltage", voltageCurrentData.getAVoltage());
                map.put("ACurrent", voltageCurrentData.getACurrent());
                map.put("BVoltage", voltageCurrentData.getBVoltage());
                map.put("BCurrent", voltageCurrentData.getBCurrent());
                map.put("CVoltage", voltageCurrentData.getCVoltage());
                map.put("CCurrent", voltageCurrentData.getCCurrent());
                fluxSink.next(map);
            }
            fluxSink.complete();
        });
        return sheet -> sheet.name("电压电流")
                             .header(new ExcelHeader("sample_time", "Time (s)", CellDataType.NUMBER))
                             .header(new ExcelHeader("rtd_vol", "Main_Voltage (V)", CellDataType.NUMBER))
                             .header(new ExcelHeader("rtd_cur", "Main_Current (A)", CellDataType.NUMBER))
                             .header(new ExcelHeader("AVoltage", "A_Voltage (V)", CellDataType.NUMBER))
                             .header(new ExcelHeader("ACurrent", "A_Current (A)", CellDataType.NUMBER))
                             .header(new ExcelHeader("BVoltage", "B_Voltage (V)", CellDataType.NUMBER))
                             .header(new ExcelHeader("BCurrent", "B_Current (A)", CellDataType.NUMBER))
                             .header(new ExcelHeader("CVoltage", "C_Voltage (V)", CellDataType.NUMBER))
                             .header(new ExcelHeader("CCurrent", "C_Current (A)", CellDataType.NUMBER))
                             .rows(dataStream);
    }


    private Consumer<SheetSpec.HeaderSheetSpec> getAmplificationData(DataAnalysisExportAmplificationParam exportParam) {

        if (exportParam.hasAmplificationData()) {
            Flux<Map<String, Object>> dataStream = Flux.create(fluxSink -> {
                JSONArray meteringData = exportParam.getMeteringSaveDataAxis();
                for (int i = 0; i < meteringData.size(); i++) {
                    Map<String, Object> map = new HashMap<>();
                    map.put("cycle", meteringData.getIntValue(i));
                    map.put("ch1_light", 0);
                    map.put("ch2_light", 0);
                    map.put("ch3_light", 0);
                    map.put("ch4_light", 0);
                    fluxSink.next(map);
                }

                fluxSink.complete();
            });

            return sheet -> sheet.name("扩增")
                                 .header(new ExcelHeader("cycle", "Cycle", CellDataType.NUMBER))
                                 .header(new ExcelHeader("ch1_light", "Fluore (VIC)", CellDataType.NUMBER))
                                 .header(new ExcelHeader("ch2_light", "Fluore (Cy5)", CellDataType.NUMBER))
                                 .header(new ExcelHeader("ch3_light", "Fluore (FAM)", CellDataType.NUMBER))
                                 .header(new ExcelHeader("ch4_light", "Fluore (ROX)", CellDataType.NUMBER))
                                 .rows(dataStream);
        } else {
            Flux<Map<String, Object>> dataStream = Flux.create(fluxSink -> {
                List<AmplificationData> amplificationDatas = exportParam.getAmplificationData();

                for (AmplificationData amplificationData : amplificationDatas) {
                    Map<String, Object> map = new HashMap<>();
                    map.put("cycle", amplificationData.getCycle());
                    map.put("fluore_vic", amplificationData.getFluoreVic());
                    map.put("fluore_cy5", amplificationData.getFluoreCy5());
                    map.put("fluore_fam", amplificationData.getFluoreFam());
                    map.put("fluore_rox", amplificationData.getFluoreRox());
                    fluxSink.next(map);
                }

                fluxSink.complete();
            });

            return sheet -> sheet.name("扩增")
                                 .header(new ExcelHeader("cycle", "Cycle", CellDataType.NUMBER))
                                 .header(new ExcelHeader("ch1_light", "Fluore (VIC)", CellDataType.NUMBER))
                                 .header(new ExcelHeader("ch2_light", "Fluore (Cy5)", CellDataType.NUMBER))
                                 .header(new ExcelHeader("ch3_light", "Fluore (FAM)", CellDataType.NUMBER))
                                 .header(new ExcelHeader("ch4_light", "Fluore (ROX)", CellDataType.NUMBER))
                                 .rows(dataStream);
        }
    }


    private Consumer<SheetSpec.HeaderSheetSpec> getMeteringDataReport(DataAnalysisExportAmplificationParam exportParam) {

        Flux<Map<String, Object>> dataStream = Flux.create(fluxSink -> {
            List<FluorescenceVoltageData> fluorescenceVoltageDatas = exportParam.getFluorescenceVoltageData();

            for (FluorescenceVoltageData fluorescenceVoltageData : fluorescenceVoltageDatas) {
                Map<String, Object> map = new HashMap<>();
                map.put("count", fluorescenceVoltageData.getCycle());
                map.put("ch1_value", fluorescenceVoltageData.getFluoreVic());
                map.put("ch2_value", fluorescenceVoltageData.getFluoreCy5());
                map.put("ch3_value", fluorescenceVoltageData.getFluoreFam());
                map.put("ch4_value", fluorescenceVoltageData.getFluoreRox());
                map.put("ch1_original", fluorescenceVoltageData.getFluoreVicOriginal());
                map.put("ch2_original", fluorescenceVoltageData.getFluoreCy5Original());
                map.put("ch3_original", fluorescenceVoltageData.getFluoreFamOriginal());
                map.put("ch4_original", fluorescenceVoltageData.getFluoreRoxOriginal());
                fluxSink.next(map); // 加这一行，确保数据流有数据
            }
            fluxSink.complete();
        });

        return sheet -> sheet.name("荧光（电压）")
                             .header(new ExcelHeader("count", "Cycle", CellDataType.NUMBER))
                             .header(new ExcelHeader("ch1_value", "Fluore(VIC)", CellDataType.NUMBER))
                             .header(new ExcelHeader("ch2_value", "Fluore(Cy5)", CellDataType.NUMBER))
                             .header(new ExcelHeader("ch3_value", "Fluore(FAM)", CellDataType.NUMBER))
                             .header(new ExcelHeader("ch4_value", "Fluore(ROX)", CellDataType.NUMBER))
                             .header(new ExcelHeader("ch1_original", "Fluore(VIC) Original(0.1V)", CellDataType.NUMBER))
                             .header(new ExcelHeader("ch2_original", "Fluore(Cy5) Original(0.1V)", CellDataType.NUMBER))
                             .header(new ExcelHeader("ch3_original", "Fluore(FAM) Original(0.1V)", CellDataType.NUMBER))
                             .header(new ExcelHeader("ch4_original", "Fluore(ROX) Original(0.1V)", CellDataType.NUMBER))
                             .rows(dataStream);
    }


    /**
     * 获取荧光(去串扰)
     *
     * @return Consumer<SheetSpec.HeaderSheetSpec>
     */
    private Consumer<SheetSpec.HeaderSheetSpec> getMeteringSaveDataReport(DataAnalysisExportAmplificationParam exportParam) {

        Flux<Map<String, Object>> dataStream = Flux.create(fluxSink -> {
            List<FluorescenceSourceData> fluorescenceSourceDatas = exportParam.getFluorescenceSourceData();
            for (FluorescenceSourceData fluorescenceSourceData : fluorescenceSourceDatas) {
                Map<String, Object> map = new HashMap<>();
                map.put("count", fluorescenceSourceData.getCycle());
                map.put("vic", fluorescenceSourceData.getFluoreVic());
                map.put("cy5", fluorescenceSourceData.getFluoreCy5());
                map.put("fam", fluorescenceSourceData.getFluoreFam());
                map.put("rox", fluorescenceSourceData.getFluoreRox());
                map.put("ch_vic", fluorescenceSourceData.getFluoreVicOriginal());
                map.put("ch_cy5", fluorescenceSourceData.getFluoreCy5Original());
                map.put("ch_fam", fluorescenceSourceData.getFluoreFamOriginal());
                map.put("ch_rox", fluorescenceSourceData.getFluoreRoxOriginal());
                fluxSink.next(map);
            }
            fluxSink.complete();
        });

        return sheet -> sheet.name("荧光(源数据)")
                             .header(new ExcelHeader("count", "Cycle", CellDataType.NUMBER))
                             .header(new ExcelHeader("vic", "Fluore(VIC)", CellDataType.NUMBER))
                             .header(new ExcelHeader("cy5", "Fluore(Cy5)", CellDataType.NUMBER))
                             .header(new ExcelHeader("fam", "Fluore(FAM)", CellDataType.NUMBER))
                             .header(new ExcelHeader("rox", "Fluore(ROX)", CellDataType.NUMBER))
                             .header(new ExcelHeader("ch_vic", "Fluore(VIC) Original", CellDataType.NUMBER))
                             .header(new ExcelHeader("ch_cy5", "Fluore(Cy5) Original", CellDataType.NUMBER))
                             .header(new ExcelHeader("ch_fam", "Fluore(FAM) Original", CellDataType.NUMBER))
                             .header(new ExcelHeader("ch_rox", "Fluore(ROX) Original", CellDataType.NUMBER))
                             .rows(dataStream);
    }

    /**
     * 替换获取计算后的CT
     *
     * @return Consumer<SheetSpec.HeaderSheetSpec>
     */
    private Consumer<SheetSpec.HeaderSheetSpec> getCT(DataAnalysisExportAmplificationParam exportParam) {

        if (exportParam.hasAmplificationData()) {
            Flux<Map<String, Object>> dataStream = Flux.create(fluxSink -> {
                JSONArray meteringData = exportParam.getMeteringSaveData();
                Map<String, Object> map = new HashMap<>();
                for (int j = 0; j < meteringData.size(); j++) {
                    JSONObject channel = meteringData.getJSONObject(j);
                    String name = channel.getString("name");
                    switch (name) {
                        case "VIC":
                            map.put("vic", meteringData.getJSONObject(j).getDoubleValue("ct"));
                            break;
                        case "Cy5":
                            map.put("cy5", meteringData.getJSONObject(j).getDoubleValue("ct"));
                            break;
                        case "FAM":
                            map.put("fam", meteringData.getJSONObject(j).getDoubleValue("ct"));
                            break;
                        case "ROX":
                            map.put("rox", meteringData.getJSONObject(j).getDoubleValue("ct"));
                            break;
                    }

                }
                fluxSink.next(map);
                fluxSink.complete();
            });

            return sheet -> sheet.name("CT")
                                 .header(new ExcelHeader("vic", "Fluore (VIC)", CellDataType.NUMBER))
                                 .header(new ExcelHeader("cy5", "Fluore (Cy5)", CellDataType.NUMBER))
                                 .header(new ExcelHeader("fam", "Fluore (FAM)", CellDataType.NUMBER))
                                 .header(new ExcelHeader("rox", "Fluore (ROX)", CellDataType.NUMBER))
                                 .rows(dataStream);
        } else {

            Flux<Map<String, Object>> dataStream = Flux.create(fluxSink -> {
                List<CTData> ctDatas = exportParam.getCtData();
                for (CTData ctData : ctDatas) {
                    Map<String, Object> map = new HashMap<>();
                    map.put("vic", ctData.getFluoreVic());
                    map.put("cy5", ctData.getFluoreCy5());
                    map.put("fam", ctData.getFluoreFam());
                    map.put("rox", ctData.getFluoreRox());
                    fluxSink.next(map);
                }
                fluxSink.complete();
            });
            return sheet -> sheet.name("CT")
                                 .header(new ExcelHeader("vic", "Fluore (VIC)", CellDataType.NUMBER))
                                 .header(new ExcelHeader("cy5", "Fluore (Cy5)", CellDataType.NUMBER))
                                 .header(new ExcelHeader("fam", "Fluore (FAM)", CellDataType.NUMBER))
                                 .header(new ExcelHeader("rox", "Fluore (ROX)", CellDataType.NUMBER))
                                 .rows(dataStream);
        }
    }


    /**
     * 获取熔解（源数据）
     *
     * @return Consumer<SheetSpec.HeaderSheetSpec>
     */
    private Consumer<SheetSpec.HeaderSheetSpec> getMeltCurveData(DataAnalysisExportAmplificationParam exportParam) {

        Flux<Map<String, Object>> dataStream = Flux.create(fluxSink -> {
            List<MeltCurveRawData> meltCurveRawDatas = exportParam.getMeltCurveRawData();
            for (MeltCurveRawData meltCurveRawData : meltCurveRawDatas) {
                Map<String, Object> map = new HashMap<>();
                map.put("temperatur1", meltCurveRawData.getVicTemperature());
                map.put("ch1_light", meltCurveRawData.getFluoreVic());
                map.put("temperatur2", meltCurveRawData.getCy5Temperature());
                map.put("ch2_light", meltCurveRawData.getFluoreCy5());
                map.put("temperatur3", meltCurveRawData.getFamTemperature());
                map.put("ch3_light", meltCurveRawData.getFluoreFam());
                map.put("temperatur4", meltCurveRawData.getRoxTemperature());
                map.put("ch4_light", meltCurveRawData.getFluoreRox());
                fluxSink.next(map);
            }
            fluxSink.complete();
        });


        return sheet -> sheet.name("熔解（原数据）")
                             .header(new ExcelHeader("temperatur1", "VIC_T (Celsius Degree)", CellDataType.NUMBER))
                             .header(new ExcelHeader("ch1_light", "Fluore (VIC)", CellDataType.NUMBER))
                             .header(new ExcelHeader("temperatur2", "Cy5_T (Celsius Degree)", CellDataType.NUMBER))
                             .header(new ExcelHeader("ch2_light", "Fluore (Cy5)", CellDataType.NUMBER))
                             .header(new ExcelHeader("temperatur3", "FAM_T (Celsius Degree)", CellDataType.NUMBER))
                             .header(new ExcelHeader("ch3_light", "Fluore (FAM)", CellDataType.NUMBER))
                             .header(new ExcelHeader("temperatur4", "ROX_T (Celsius Degree)", CellDataType.NUMBER))
                             .header(new ExcelHeader("ch4_light", "Fluore (ROX)", CellDataType.NUMBER))
                             .rows(dataStream);
    }


    /**
     * 替换-获取熔解（计算后）
     *
     * @return Consumer<SheetSpec.HeaderSheetSpec>
     */
    private Consumer<SheetSpec.HeaderSheetSpec> getMeltCurveCuleData(DataAnalysisExportAmplificationParam exportParam) {

        if (exportParam.hasMeltCurveData()) {

            Flux<Map<String, Object>> dataStream = Flux.create(fluxSink -> {
                JSONArray meltCurveData = exportParam.getMeltCurveData();
                if (meltCurveData == null || meltCurveData.isEmpty()) {
                    fluxSink.complete();
                    return;
                }

                // 获取第一个通道的data数组长度作为基准
                JSONObject firstChannel = meltCurveData.getJSONObject(0);
                JSONArray dataArray = firstChannel.getJSONArray("data");
                int size = dataArray.size();

                for (int i = 0; i < size; i++) {
                    Map<String, Object> map = new HashMap<>();
                    for (int j = 0; j < meltCurveData.size(); j++) {
                        if (j >= meltCurveData.size()) break;

                        JSONObject channel = meltCurveData.getJSONObject(j);
                        if (!channel.containsKey("data")) continue;

                        JSONArray channelData = channel.getJSONArray("data");
                        if (i >= channelData.size()) continue;

                        String name = channel.getString("name");
                        double dataValue = channelData.getDouble(i);

                        switch (name) {
                            case "VIC":
                                map.put("ch1_light_d", dataValue);
                                map.put("temperatur1", 0.0);
                                break;
                            case "Cy5":
                                map.put("ch2_light_d", dataValue);
                                map.put("temperatur2", 0.0);
                                break;
                            case "FAM":
                                map.put("ch3_light_d", dataValue);
                                map.put("temperatur3", 0.0);
                                break;
                            case "ROX":
                                map.put("ch4_light_d", dataValue);
                                map.put("temperatur4", 0.0);
                                break;
                        }
                    }
                    fluxSink.next(map);
                }
                fluxSink.complete();
            });
            return sheet -> sheet.name("熔解（后处理）")
                                 .header(new ExcelHeader("temperatur1", "T_VIC", CellDataType.NUMBER))
                                 .header(new ExcelHeader("ch1_light_d", "Diff (VIC)", CellDataType.NUMBER))
                                 .header(new ExcelHeader("temperatur2", "T_Cy5", CellDataType.NUMBER))
                                 .header(new ExcelHeader("ch2_light_d", "Diff (Cy5)", CellDataType.NUMBER))
                                 .header(new ExcelHeader("temperatur3", "T_FAM", CellDataType.NUMBER))
                                 .header(new ExcelHeader("ch3_light_d", "Diff (FAM)", CellDataType.NUMBER))
                                 .header(new ExcelHeader("temperatur4", "T_ROX", CellDataType.NUMBER))
                                 .header(new ExcelHeader("ch4_light_d", "Diff (ROX)", CellDataType.NUMBER))
                                 .rows(dataStream);
        } else {

            Flux<Map<String, Object>> dataStream = Flux.create(fluxSink -> {
                List<MeltCurveProcessedData> meltCurveProcessedDatas = exportParam.getMeltCurveProcessedData();
                for (MeltCurveProcessedData meltCurveProcessedData : meltCurveProcessedDatas) {
                    Map<String, Object> map = new HashMap<>();
                    map.put("temperatur1", meltCurveProcessedData.getTVic());
                    map.put("ch1_light_d", meltCurveProcessedData.getDiffVic());
                    map.put("temperatur2", meltCurveProcessedData.getTCy5());
                    map.put("ch2_light_d", meltCurveProcessedData.getDiffCy5());
                    map.put("temperatur3", meltCurveProcessedData.getTFam());
                    map.put("ch3_light_d", meltCurveProcessedData.getDiffFam());
                    map.put("temperatur4", meltCurveProcessedData.getTRox());
                    map.put("ch4_light_d", meltCurveProcessedData.getDiffRox());
                    fluxSink.next(map);
                }
                fluxSink.complete();
            });

            return sheet -> sheet.name("熔解（后处理）")
                                 .header(new ExcelHeader("temperatur1", "T_VIC", CellDataType.NUMBER))
                                 .header(new ExcelHeader("ch1_light_d", "Diff (VIC)", CellDataType.NUMBER))
                                 .header(new ExcelHeader("temperatur2", "T_Cy5", CellDataType.NUMBER))
                                 .header(new ExcelHeader("ch2_light_d", "Diff (Cy5)", CellDataType.NUMBER))
                                 .header(new ExcelHeader("temperatur3", "T_FAM", CellDataType.NUMBER))
                                 .header(new ExcelHeader("ch3_light_d", "Diff (FAM)", CellDataType.NUMBER))
                                 .header(new ExcelHeader("temperatur4", "T_ROX", CellDataType.NUMBER))
                                 .header(new ExcelHeader("ch4_light_d", "Diff (ROX)", CellDataType.NUMBER))
                                 .rows(dataStream);
        }
    }


    /**
     * 替换-计算的熔解结果，获取rm tm
     *
     * @return Consumer<SheetSpec.HeaderSheetSpec>
     */
    private Consumer<SheetSpec.HeaderSheetSpec> getTrim(DataAnalysisExportAmplificationParam exportParam) {

        if (exportParam.hasMeltCurveData()) {


            Flux<Map<String, Object>> dataStream = Flux.create(fluxSink -> {
                JSONArray meltCurveData = exportParam.getMeltCurveData();
                if (meltCurveData == null || meltCurveData.isEmpty()) {
                    fluxSink.complete();
                    return;
                }

                // 获取第一个通道的tm数组长度作为基准
                JSONObject firstChannel = meltCurveData.getJSONObject(0);
                JSONArray tmArray = firstChannel.getJSONArray("tm");
                JSONArray rmArray = firstChannel.getJSONArray("rm");
                int size = Math.min(tmArray.size(), rmArray.size());

                for (int i = 0; i < size; i++) {
                    Map<String, Object> map = new HashMap<>();
                    for (int j = 0; j < meltCurveData.size(); j++) {
                        if (j >= meltCurveData.size()) break; // 防止索引越界

                        JSONObject channel = meltCurveData.getJSONObject(j);
                        if (!channel.containsKey("tm") || !channel.containsKey("rm")) continue;

                        JSONArray tm = channel.getJSONArray("tm");
                        JSONArray rm = channel.getJSONArray("rm");
                        if (i >= tm.size() || i >= rm.size()) continue; // 跳过不完整的条目

                        String name = channel.getString("name");
                        double tmValue = tm.getDouble(i);
                        double rmValue = rm.getDouble(i);

                        switch (name) {
                            case "VIC":
                                map.put("ch1_light_t", tmValue);
                                map.put("ch1_light_rm", rmValue);
                                break;
                            case "Cy5":
                                map.put("ch2_light_t", tmValue);
                                map.put("ch2_light_rm", rmValue);
                                break;
                            case "FAM":
                                map.put("ch3_light_t", tmValue);
                                map.put("ch3_light_rm", rmValue);
                                break;
                            case "ROX":
                                map.put("ch4_light_t", tmValue);
                                map.put("ch4_light_rm", rmValue);
                                break;
                        }
                    }
                    fluxSink.next(map);
                }
                fluxSink.complete();
            });

            return sheet -> sheet.name("熔解结果")
                                 .header(new ExcelHeader("ch1_light_t", "Tm_VIC", CellDataType.NUMBER))
                                 .header(new ExcelHeader("ch1_light_rm", "Rm_VIC", CellDataType.NUMBER))
                                 .header(new ExcelHeader("ch2_light_t", "Tm_Cy5", CellDataType.NUMBER))
                                 .header(new ExcelHeader("ch2_light_rm", "Rm_Cy5", CellDataType.NUMBER))
                                 .header(new ExcelHeader("ch3_light_t", "Tm_FAM", CellDataType.NUMBER))
                                 .header(new ExcelHeader("ch3_light_rm", "Rm_FAM", CellDataType.NUMBER))
                                 .header(new ExcelHeader("ch4_light_t", "Tm_ROX", CellDataType.NUMBER))
                                 .header(new ExcelHeader("ch4_light_rm", "Rm_ROX", CellDataType.NUMBER))
                                 .rows(dataStream);
        } else {
            Flux<Map<String, Object>> dataStream = Flux.create(fluxSink -> {
                List<MeltCurveResultData> meltCurveResultDatas = exportParam.getMeltCurveResultData();
                for (MeltCurveResultData meltCurveResultData : meltCurveResultDatas) {
                    Map<String, Object> map = new HashMap<>();
                    map.put("ch1_light_t", meltCurveResultData.getTmVic());
                    map.put("ch1_light_rm", meltCurveResultData.getRmVic());
                    map.put("ch2_light_t", meltCurveResultData.getTmCy5());
                    map.put("ch2_light_rm", meltCurveResultData.getRmCy5());
                    map.put("ch3_light_t", meltCurveResultData.getTmFam());
                    map.put("ch3_light_rm", meltCurveResultData.getRmFam());
                    map.put("ch4_light_t", meltCurveResultData.getTmRox());
                    map.put("ch4_light_rm", meltCurveResultData.getRmRox());
                    fluxSink.next(map);
                }
                fluxSink.complete();
            });


            return sheet -> sheet.name("熔解结果")
                                 .header(new ExcelHeader("ch1_light_t", "Tm_VIC", CellDataType.NUMBER))
                                 .header(new ExcelHeader("ch1_light_rm", "Rm_VIC", CellDataType.NUMBER))
                                 .header(new ExcelHeader("ch2_light_t", "Tm_Cy5", CellDataType.NUMBER))
                                 .header(new ExcelHeader("ch2_light_rm", "Rm_Cy5", CellDataType.NUMBER))
                                 .header(new ExcelHeader("ch3_light_t", "Tm_FAM", CellDataType.NUMBER))
                                 .header(new ExcelHeader("ch3_light_rm", "Rm_FAM", CellDataType.NUMBER))
                                 .header(new ExcelHeader("ch4_light_t", "Tm_ROX", CellDataType.NUMBER))
                                 .header(new ExcelHeader("ch4_light_rm", "Rm_ROX", CellDataType.NUMBER))
                                 .rows(dataStream);
        }
    }
    public Consumer<SheetSpec.HeaderSheetSpec> getRecordSheet(DataAnalysisExportAmplificationParam exportParam) {

            return sheet -> {
//
//            设备名称（ID）_模块名称（ID）_实验人员账号
//（载体编码）
//            检测项：（库+检测项名）或者（用户自定义+检测项名），测光通道：（库 + 测光通道）或者（用户自定义 + 测光通道），程序：（库 + 程序名称）或者（用户自定义 + 程序名称）
//            完成度：x%，实验时长：x分x秒

                Flux<Map<String, Object>> dataStream = Flux.create(fluxSink -> {

                        Map<String, Object> map = new HashMap<>();
                        map.put("i", "-");
                        map.put("type", "-");
                        map.put("temperature","-");
                        map.put("speed", "-");
                        map.put("delay", "-");
                        map.put("light", "-");
                        map.put("data", "-");
                        fluxSink.next(map);
                    fluxSink.complete();
                });


                sheet.name("实验信息")
                     .cell(0, 0, "------------------")
                     //自定义sheet操作
                     .option(sheet_ -> {
                         sheet_.addMergedRegion(CellRangeAddress.valueOf("A1:F1"));
                     });
                sheet.header(new ExcelHeader("i", "序号", CellDataType.NUMBER))
                     .header("type", "类型")
                     .header(new ExcelHeader("temperature", "温度", CellDataType.NUMBER))
                     .header(new ExcelHeader("speed", "速度（Celsius Degree/s）", CellDataType.NUMBER))
                     .header(new ExcelHeader("delay", "时间", CellDataType.NUMBER))
                     .header("light", "是否测光")
                     .rows(dataStream)
                     .firstRowIndex(1);
            };

    }


    /**
     * 设备状态
     *
     * @return Consumer<SheetSpec.HeaderSheetSpec>
     */
    public Consumer<SheetSpec.HeaderSheetSpec> getDeviceStateData(DataAnalysisExportAmplificationParam exportParam) {
//        String jsonString = "{\"batchId\":\"\",\"calibration\":0,\"carrier\":1,\"ch1_init_status\":1,\"ch1_run_status\":0,\"ch2_init_status\":1,\"ch2_run_status\":0,\"ch3_init_status\":1,\"ch3_run_status\":0,\"ch4_init_status\":1,\"ch4_run_status\":0,\"cold_head_temp\":0,\"cover_plate\":1,\"cover_plate_carrier_status\":0,\"heater_err_str\":\"\",\"heater_init_stauts\":1,\"heater_reference_temp\":3000,\"heater_rtd_temp\":3000,\"heater_status\":1,\"init\":1,\"leave_time\":10000,\"schedule\":100,\"status\":1,\"water_cooler_box_temp\":0,\"water_cooler_err_str\":\"\",\"water_cooler_errer\":0,\"water_cooler_init_status\":1,\"water_cooler_seft_check\":3}";



            return sheet -> sheet
                .name("状态信息")
                .cell(0, 0, "设备端上位机版本号")
                .cell(0, 1, "-")
                .cell(1, 0, "设备端下位机版本号")
                .cell(1, 1, "-")
                .cell(2, 0, "模块初始化状态")
                .cell(2, 1, "-")
                .cell(3, 0, "加热器初始化状态")
                .cell(3, 1, "-")
                .cell(4, 0, "加热器校准状态")
                .cell(4, 1, "-")
                .cell(5, 0, "加热器参数")
                .cell(5, 1, "-")
                .cell(6, 0, "加热器健康状态")
                .cell(6, 1, "-")
                .cell(7, 0, "冷却器初始化状态")
                .cell(7, 1, "-")
                .cell(8, 0, "冷却器健康状态")
                .cell(8, 1, "-")
                .cell(9, 0, "测光通道1初始化状态")
                .cell(9, 1, "-")
                .cell(10, 0, "测光通道1健康状态")
                .cell(10, 1, "-")
                .cell(11, 0, "测光通道2初始化状态")
                .cell(11, 1, "-")
                .cell(12, 0, "测光通道2健康状态")
                .cell(12, 1, "-")
                .cell(13, 0, "测光通道3初始化状态")
                .cell(13, 1, "-")
                .cell(14, 0, "测光通道3健康状态")
                .cell(14, 1, "-")
                .cell(15, 0, "测光通道4初始化状态")
                .cell(15, 1, "-")
                .cell(16, 0, "测光通道4健康状态")
                .cell(16, 1, "-");


    }

}
